# -*- coding: utf-8-sig -*-
#!/usr/bin/python

'''Módulo que contiene el modelo de la Base de Datos

Este módulo es el que se utiliza en todos los apps.
'''
__author__ =  'Luis Aldana','Martín Guzmán','Byron Morales'
__version__=  '1.0'


from django.db import models
from XMLParser import *
from django.conf import settings
import os, datetime, Image
from django.utils.encoding import smart_str
from PIL import Image

class Deporte(models.Model):
    '''Describe a la tabla de Deporte

    Parámetros:
    nombre -- cadena de longitud 30 que representa el nombre del deporte
    xml -- campo de texto que contiene la información sobre los deportes, disciplinas,
     categorías y requerimientos para un determinado deporte
    '''
    activo = models.BooleanField(default=True)
    nombre = models.CharField(max_length=30)
    xml = models.TextField()
    
    @staticmethod
    def getAllObjects():
        lista = []
        for dep in Deporte.objects.all():
            a = dep.getXMLObject()
            lista.append(a)
        return lista
        
    
    def getXMLObject(self):
        try:
            a = self.xml.encode('utf-8')
        except:
            a = self.xml
        b = xml_parser(a)[0]
        return b
    
    def __unicode__(self):
        return self.nombre

class Entrenador(models.Model):
    '''Describe a la tabla de Entrenador

    Parámetros:
    nombres -- cadena de longitud 50 que representa todos los nombres del entrenador
    apellidos -- cadena de longitud 50 que representa todos los apellidos del entrenador
    telefono_celular -- cadena que guarda el número de celular del entrenador
    telefono -- cadena que guarda el número de teléfono del entrenador
    correo_electronico -- atributo con la validación para un correo electrónico
    deportes -- lista de deportes en los que ayuda a entrenar a los atletas
    '''
    #información personal del entrenador
    activo = models.BooleanField(default=True)
    
    nombres = models.CharField(max_length=50)
    apellidos = models.CharField(max_length=50)
    url_foto = models.CharField(max_length=150, default='entrenadores/default.png')
    
    #información de contacto
    telefono_celular = models.CharField(max_length=10, blank=True)
    telefono = models.CharField(max_length=10, blank=True)
    correo_electronico = models.EmailField(blank=True)
    
    #deportes a los que está asociado
    deportes = models.ManyToManyField(Deporte, verbose_name="Lista de deportes", blank=True)
    
    def set_foto(self, f=None, url_nueva=''):
        
        if url_nueva!='':
            self.url_foto = url_nueva
            return
        
        url = 'entrenadores/'
        name = str(self.pk)+'.png'
        file_path = settings.PROJECT_ROOT+os.path.join(settings.STATIC_URL, 'media/'+url)+name
        
        if f==None:
            return
            
        try:
			foto = Image.open(f)
			foto.save(file_path)
            #des = open(file_path,'w')
            #for chunk in f.chunks():
            #    des.write(chunk)
            #des.close()
        except:
            name = 'default.png'
        self.url_foto = url+name
    
    
    def __unicode__(self):
        return self.nombres + ' '+self.apellidos
    

class Atleta(models.Model):
    '''Describe a la tabla de Atleta

    Parámetros:
    activo -- atributo booleano que representa si el atleta está activo o no
    nombres -- cadena de longitud 50 que representa todos los nombres del atleta
    apellidos -- cadena de longitud 50 que representa todos los apellidos del atleta
    fecha_nacimiento -- atributo que contiene la fecha de nacimiento del atleta
    pasaporte -- atributo con el número de pasaporte del atleta
    estudios -- atributo que puede contener uno de los siguientes: {Primaria, Básico, Diversificado, Universitario, Otro}
    identificacion_personal_tipo -- atributo que representa el tipo de id personal {Cédula de vecindad, DPI, Licencia, Pasaporte}
    identificacion_personal_valor -- atributo que contiene la información de id personal según el tipo
    
    deportes -- lista de deportes practicados por el atleta
    
    telefono_celular -- cadena que representa el teléfono celular del atleta
    telefono -- cadena que representa otro teléfono del atleta
    correo_electronico -- atributo con la validación para un correo electrónico
    direccion -- cadena que contiene la dirección de la vivienda del atleta
    direccion_municipio -- cadena que contiene el municipio de la vivienda del atleta
    direccion_departamento -- cadena que contiene el municipio de la vivienda del atleta
    
    encargado_nombres -- cadena que contiene los nombres del encargado del atleta
    encargado_apellidos -- cadena que contiene los apellidos del encargado del atleta
    encargado_identificacion_personal_tipo -- atributo que representa el tipo de identificación personal del encargado
    encargado_identificacion_personal_valor = atributo que contiene la información de id según el tipo (del encargado)
    encargado_telefono_celular = contiene el número de teléfono celular del encargado
    encargado_telefono = contiene el número de teléfono del encargado
    encargado_correo = atributo con la validación para un correo electrónico del encargado
    
    entrenadores -- lista de entrenadores del atleta (hace referencia a la clase entrenador)
    
    peso -- contiene el peso del atleta
    estatura -- contiene la estatura del atleta en centímetros
    grupo_sanguineo -- contiene el grupo sanguíneo del atleta según la lista: {O+,O-,A+,A-,B+,B-,AB+,AB-}
    alergias_enfermedades -- cadena de longitud 200 que contiene una lista de las alergias o enfermedades que tiene el atleta
    
    '''
    
    #información personal del atleta
    activo = models.BooleanField(default=True)
    
    nombres = models.CharField(max_length=50)
    apellidos = models.CharField(max_length=50)
    fecha_nacimiento = models.DateField()
    SEXO_CHOICES = (
        ('Masculino','Masculino'),
        ('Femenino','Femenino')
    )
    sexo = models.CharField(max_length=10, choices=SEXO_CHOICES)
    pasaporte = models.CharField(max_length=50, blank=True)
    ESTUDIOS_CHOICES = (
        ('Primaria','Primaria'),
        (u'Básico','Básico'),
        ('Diversificado','Diversificado'),
        ('Universitario','Universitario'),
        ('Otro','Otro')
    )
    estudios = models.CharField(max_length=20, choices=ESTUDIOS_CHOICES, blank=True)
    ID_PERSONAL_CHOICES = (
        (u'Cédula de vecindad','Cédula de vecindad'),
        ('DPI','DPI'),
        ('Pasaporte','Pasaporte'),
        ('Otro','Otro'),
    )
    identificacion_personal_tipo = models.CharField(max_length=20, choices=ID_PERSONAL_CHOICES, blank=True)
    identificacion_personal_valor = models.CharField(max_length=20, blank=True)
    url_foto = models.CharField(max_length=150, default='atletas/default.png', blank=True)
    
    #información de deportes
    deportes = models.ManyToManyField(Deporte, verbose_name="Lista de deportes", blank=True)
    
    #información de contacto
    telefono_celular = models.CharField(max_length=10, blank=True)
    telefono = models.CharField(max_length=10, blank=True)
    correo_electronico = models.EmailField(blank=True)
    direccion = models.CharField(max_length=150, blank=True)
    direccion_municipio = models.CharField(max_length=20, blank=True)
    direccion_departamento = models.CharField(max_length=20, blank=True)
    
    #infomación de encargado
    encargado_nombres = models.CharField(max_length=50, blank=True)
    encargado_apellidos = models.CharField(max_length=50, blank=True)
    encargado_identificacion_personal_tipo = models.CharField(max_length=20, choices=ID_PERSONAL_CHOICES, blank=True)
    encargado_identificacion_personal_valor = models.CharField(max_length=20, blank=True)
    encargado_telefono_celular = models.CharField(max_length=10, blank=True)
    encargado_telefono = models.CharField(max_length=10, blank=True)
    encargado_correo = models.EmailField(blank=True)
    
    #información de entrenador
    entrenadores = models.ManyToManyField(Entrenador, verbose_name="Lista de entrenadores", blank=True)
    
    #información médica
    peso = models.IntegerField(default=0)
    estatura = models.IntegerField(default=0)
    SANGRE_CHOICES = (
        ('O+','O+'),
        ('O-','O-'),
        ('A+','A+'),
        ('A-','A-'),
        ('B+','B+'),
        ('B-','B-'),
        ('AB+','AB+'),
        ('AB-','AB-')
    )
    grupo_sanguineo = models.CharField(max_length=3, choices=SANGRE_CHOICES, blank=True)
    alergias_enfermedades = models.CharField(max_length=200, blank=True)
    
    def set_foto(self, f=None, url_nueva=''):
        
        if url_nueva!='':
            self.url_foto = url_nueva
            return
        
        url = 'atletas/'
        name = str(self.pk)+'.png'
        file_path = settings.PROJECT_ROOT+os.path.join(settings.STATIC_URL, 'media/'+url)+name
        
        if f==None:
            return
            
        try:
			foto = Image.open(f)
			foto.save(file_path)
            #des = open(file_path,'w')
            #for chunk in f.chunks():
            #    des.write(chunk)
            #des.close()
        except:
            name = 'default.png'
        self.url_foto = url+name
    
    def get_edad(self, to_date=datetime.date.today()):
        '''
        Ejemplo de cómo calcula la edad:
        sea fecha_nacimiento = 1989/12/6
            to_date = 2011/11/1
            new_date = 2011/12/6 -> el cumpleaños al año que se quiere
            edad = 2011-1989 = 22
        Si ya pasó su cumpleaños, esa es su edad. De lo contrario se le resta 1
        Para saber si ya pasó obtenemos (to_date-new_date).days.
            En este caso esta operación nos devuelve -32 días (faltan 32 días para el cumpleaños)
            edad = edad -1 = 21
        '''
        fecha = self.fecha_nacimiento
        # calcula la fecha de cumpleaños a la fecha con la que se quiere evaluar
        new_date = datetime.date(to_date.year,fecha.month,fecha.day)
        edad = to_date.year-fecha.year
        #si ya pasó el cumpleaños, la edad se queda igual
        if (to_date-new_date).days<0:
            #no ha llegado su cumpleaños, se le resta 1
            edad = edad-1
        return edad
        
    
    def __unicode__(self):
        return self.nombres + " " + self.apellidos
        
    def nombre_completo(self):
        return self.nombres + " " + self.apellidos
    
    @staticmethod
    def attr_dict():
        '''
        Método que retorna un diccionario con los atributos que se pueden asignar
        como datos requeridos en la creación de un deporte.
        '''
        dict = {}
        #~ dict['Activo']='activo'
        dict[u'Nombres']='nombres'
        dict[u'Apellidos']='apellidos'
        dict[u'Fecha de Nacimiento']='fecha_nacimiento'
        dict[u'Sexo']='sexo'
        dict[u'Número de Pasaporte']='pasaporte'
        dict[u'Nivel de Estudios']='estudios'
        dict[u'Documento de Identificación Personal']='identificacion_personal_tipo'
        dict[u'Número de Identificación Personal']='identificacion_personal_valor'
        
        # No agregué "deportes" porque no parece factible que se vaya a usar.
        
        dict[u'Número de Celular']='telefono_celular'
        dict[u'Número de Teléfono']='telefono'
        dict[u'Correo Electrónico']='correo_electronico'
        dict[u'Dirección']='direccion'
        dict[u'Municipio']='direccion_municipio'
        dict[u'Departamento']='direccion_departamento'
        
        dict[u'Nombres del Encargado']='encargado_nombres'
        dict[u'Apellidos del Encargado']='encargado_apellidos'
        dict[u'Tipo de Identificación Personal del Encargado']='encargado_identificacion_personal_tipo'
        dict[u'Número de Identificación Personal del Encargado']='encargado_identificacion_personal_valor'
        dict[u'Número de Celular del Encargado']='encargado_telefono_celular'
        dict[u'Número de Teléfono del Encargado']='encargado_telefono'
        dict[u'Correo Electrónico']='encargado_correo'
        
        # Tampoco se agregan los entrenadores
        
        dict[u'Peso']='peso'
        dict[u'Estatura']='estatura'
        dict[u'Grupo Sanguíneo']='grupo_sanguineo'
        dict[u'Alergias/Enfermedades']='alergias_enfermedades'
        
        return dict
    
    @staticmethod
    def get_attr_key(value=''):
        dict = Atleta.attr_dict()
        res = [k for k, v in dict.iteritems() if v == value]
        if len(res)!=0:
            return res[0]
        return ''
    
class Evento(models.Model):
    '''Desribe la tabla de Evento

    Parámetros:
    nombre -- Cadena de longitud 30 que representa el nombre del evento.
    edicion -- Número entero que representa la edición del evento.
    fecha_inicio -- Fecha que marca el inicio del evento.
    fecha_fin -- Fecha que marca el final del evento.
    deportes -- Lista de deportes del evento. No se inicializa al crear el evento.
    atletas -- Lista de atletas del evento. No se inicializa al crear el evento.
    '''
    nombre = models.CharField(max_length=40)
    edicion = models.CharField(max_length=20,blank=True)
    fecha_inicio = models.DateField()
    fecha_fin = models.DateField()
    deportes = models.ManyToManyField(Deporte, verbose_name="Lista de deportes del evento", blank=True)
    atletas = models.ManyToManyField(Atleta, through='Participacion' , verbose_name="Lista de atletas participantes", blank=True)
    xml = models.TextField(blank=True)
    def __unicode__(self):
        return self.nombre+u" "+str(self.edicion)

    def getXMLObjectList(self):
        try:
            a = self.xml.encode('utf-8')
        except:
            a = self.xml
        b = xml_parser(a)
        return b
    

class Participacion(models.Model):
    '''Tabla intermedia de relación entre Atleta y Evento.
   
    Parámetros:
    evento -- Llave foránea de tipo Evento.
    atleta -- Llave foránea de tipo Atleta.
    xml_resultado -- XML que contiene las categorías en las que participó y los resultados.
    '''
    evento = models.ForeignKey(Evento)
    atleta = models.ForeignKey(Atleta)
    xml_resultado = models.TextField(blank=True)
    
    class Meta:
        unique_together = (('evento','atleta'),)
    
    
    def getXMLObjectList(self):
        try:
            a = self.xml_resultado.encode('utf-8')
        except:
            a = self.xml_resultado
        b = xml_parser(a)
        return b
    
    def getXMLObjectListRes(self):
        b = self.getXMLObjectList()
        for dep in b:
            for dis in dep.disciplinas:
                for cat in dis.categorias:
                    if len(cat.resultados)>0:
                        dep.contiene_resultados = True
                        dis.contiene_resultados = True
                        cat.contiene_resultados = True
        return b
    
    def unResultado(self):
        for dep in self.getXMLObjectList():
            for dis in dep.disciplinas:
                for cat in dis.categorias:
                    if len(cat.resultados)>0:
                        return True
        return False
        
